class FileUploader {
    constructor(options) {
        this.file = options.file;
        this.chunkSize = options.chunkSize || 1024 * 1024;
        this.uploadUrl = options.uploadUrl || '/filetrans/files';
        this.concurrent = options.concurrent || 10; // 并发数
        this.onProgress = options.onProgress || (() => {
        });
        this.onComplete = options.onComplete || (() => {
        });
        this.onError = options.onError || (() => {
        });
        this.uploadId = null;
    }

    async start() {
        try {
            // 1. 初始化上传
            const initResponse = await fetch(`${this.uploadUrl}/upload/init`, {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/x-www-form-urlencoded',
                },
                body: new URLSearchParams({
                    fileName: this.file.name,
                    fileSize: this.file.size,
                    lastModified: this.file.lastModified,
                    chunkSize: this.chunkSize,
                    categoryId: this.categoryId || ''
                })
            });

            this.uploadId = await initResponse.text();

            // 2. 分片上传
            const totalChunks = Math.ceil(this.file.size / this.chunkSize);
            const chunks = Array.from({length: totalChunks}, (_, i) => i);

            // 使用并发控制上传
            await this.uploadChunksConcurrently(chunks);

            // 3. 完成上传
            const completeResponse = await fetch(`${this.uploadUrl}/upload/complete`, {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/x-www-form-urlencoded',
                },
                body: new URLSearchParams({
                    uploadId: this.uploadId
                })
            });

            const fileId = await completeResponse.text();
            this.onComplete(fileId);
        } catch (error) {
            this.onError(error);
        }
    }

    async uploadChunksConcurrently(chunks) {
        const queue = [...chunks];
        const active = new Set();
        let errors = [];
        let progressInterval;

        // 定义启动定时进度更新
        const startProgressUpdates = () => {
            progressInterval = setInterval(() => {
                this.updateProgress();
            }, 2000);
        };

        // 定义停止进度更新
        const stopProgressUpdates = () => {
            if (progressInterval) {
                clearInterval(progressInterval);
                progressInterval = null;
            }
        };

        try {
            startProgressUpdates();
            while (queue.length > 0 || active.size > 0) {
                if (active.size < this.concurrent && queue.length > 0) {
                    const chunkNumber = queue.shift();
                    active.add(chunkNumber);

                    this.uploadChunk(chunkNumber)
                        .then(() => {
                            active.delete(chunkNumber);
                        })
                        .catch(error => {
                            errors.push(error);
                            active.delete(chunkNumber);
                        });
                } else {
                    await new Promise(resolve => setTimeout(resolve, 100));
                }

                if (errors.length > 0) {
                    throw errors[0];
                }
            }
        } finally {
            stopProgressUpdates();
            this.updateProgress();
        }

    }

    async generateChunkSignature(chunk) {
        const sampleSize = 1024;
        const sample = chunk.slice(0, Math.min(sampleSize, chunk.size));
        const buffer = await sample.arrayBuffer();

        return this.quickHash(new Uint8Array(buffer));
    }

    quickHash(data) {
        let hash = 0;
        for (let i = 0; i < data.length; i += 4) {
            hash = ((hash << 5) - hash) + data[i];
            hash = hash & hash;
        }
        return hash.toString(36);
    }

    async uploadChunk(chunkNumber) {
        const start = chunkNumber * this.chunkSize;
        const end = Math.min(start + this.chunkSize, this.file.size);
        const chunk = this.file.slice(start, end);
        const hash = await this.generateChunkSignature(chunk)

        const formData = new FormData();
        formData.append('uploadId', this.uploadId);
        formData.append('hash', hash);
        formData.append('chunkNumber', chunkNumber);

        const response = await fetch(`${this.uploadUrl}/check/chunk`, {
            method: 'POST',
            body: formData
        });
        const data = await response.text(); // 后端返回纯文本

        if (data === '0') {
            formData.append('chunk', chunk, this.file.name);
            await fetch(`${this.uploadUrl}/upload/chunk`, {
                method: 'POST',
                body: formData
            });
        }
    }

    async updateProgress() {
        if (!this.uploadId) return;

        const response = await fetch(`${this.uploadUrl}/upload/progress/${this.uploadId}`);
        const progress = await response.json();
        this.onProgress(progress);
    }
}

document.getElementById('upload-btn').addEventListener('click', async () => {
    const uploadBtn = document.getElementById('upload-btn');
    uploadBtn.disabled = true;

    const fileInput = document.getElementById('file-input');
    if (fileInput.files.length === 0) return;

    const progressContainer = document.getElementById('upload-progress');
    const progressBar = progressContainer.querySelector('.progress-bar');
    const progressText = progressContainer.querySelector('.progress-text');
    const uploadStatus = progressContainer.querySelector('.upload-status');


    // 显示进度条
    progressContainer.style.display = 'block';
    progressBar.style.width = '0%';
    progressText.textContent = '0%';
    uploadStatus.textContent = '准备上传...';


    const uploader = new FileUploader({
        file: fileInput.files[0],
        chunkSize: null,
        onProgress: (progress) => {
            progressBar.style.width = `${progress}%`;
            progressText.textContent = `${progress}%`;
            if (progress === 100) {
                uploadStatus.textContent = '合并中...';
            } else {
                uploadStatus.textContent = '上传中...';
            }
        },
        onComplete: (fileId) => {
            progressText.textContent = '上传完成';
            uploadBtn.disabled = false;
            setTimeout(() => location.reload(), 1000);
        },
        onError: (error) => {
            console.error('上传失败:', error);
            progressText.textContent = '上传失败';
            uploadBtn.disabled = false;
        }
    });

    progressBar.style.width = '0%';
    progressText.textContent = '0%';
    uploader.start();
});